/*
**  editor .c
**  Copyright 2011, Zane Sims
**
**  This file is part of brick-breaker-game.
**
**  brick-breaker-game is free software: you can redistribute it
**  and/or modify it under the terms of the GNU General Public
**  License as published by the Free Software Foundation, either
**  version 3 of the License, or (at your option) any later version.
**
**  brick-breaker-game is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with brick-breaker-game.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_native_dialog.h>

#include "common.h"
#include "gui.h"

#define SELECT_GRID_W	20
#define SELECT_GRID_H	2
#define SCREEN_W		790
#define SCREEN_H		550
#define FPS				60

/* I refuse to believe that globals are a no-no */
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
ALLEGRO_TIMER *frame_timer = NULL;
ALLEGRO_FONT *editor_font = NULL;
ClickableSet *main_set = NULL;
Clickable *brick_grid_clickables[BRICK_GRID_W][BRICK_GRID_H];
Clickable *select_grid_clickable = NULL;
Clickable *new_button = NULL;
Clickable *open_button = NULL;
Clickable *save_button = NULL;
Clickable *saveas_button = NULL;
int left_mouse_button_down = 0;
int right_mouse_button_down = 0;
int mouse_pos_x = 0;
int mouse_pos_y = 0;
char filename[256] = {'\0'};
int select_grid_types[40];
int selected_index = 0;
int brick_pos_i = -1;
int brick_pos_j = -1;
int saved = 1;

void clean_up()
{
	/*destroy things if they aren't NULL*/
	free_images();
	free_clickable_set(main_set);
	al_destroy_font(editor_font);
	al_destroy_timer(frame_timer);
	al_destroy_display(display);
	al_destroy_event_queue(event_queue);
}

int save_level(const char* fn)
{
	FILE *fp = NULL;
	int i = 0;
	int j = 0;

	if(!(fp=fopen(fn, "wb+")))
		return 0;

	fwrite("BRICKLEVEL", 1, 10, fp);

	for(j=0;j<BRICK_GRID_H;j++)
	{
		for(i=0;i<BRICK_GRID_W;i++)
		{
			fwrite(&(bricks[i][j].img_index), 1, 1, fp);
			fwrite(&(bricks[i][j].type), 1, 1, fp);
		}
	}

	fclose(fp);
	return 1;
}

int button_click(int mx, int my, struct _Clickable *c)
{
	ALLEGRO_FILECHOOSER *dialog = NULL;
	const char *fn = NULL;

	if(c == new_button)
	{
		if(saved || al_show_native_message_box(display, "Warning!", "Warning!", "You have unsaved changes. Are you sure you want to continue?", NULL, ALLEGRO_MESSAGEBOX_YES_NO) == 1)
		{
			load_level(NULL);
			saved = 1;
			filename[0] = '\0';
		}
	}
	else if(c == open_button)
	{
		if(saved || al_show_native_message_box(display, "Warning!", "Warning!", "You have unsaved changes. Are you sure you want to continue?", NULL, ALLEGRO_MESSAGEBOX_YES_NO) == 1)
		{
			dialog = al_create_native_file_dialog("levels/", "Open Level", "*.*", ALLEGRO_FILECHOOSER_FILE_MUST_EXIST);
			
			if(!al_show_native_file_dialog(display, dialog))
				error_exit("Error: unable to display file chooser dialog!");

			if((fn=al_get_native_file_dialog_path(dialog, 0)) == NULL)
			{
				al_destroy_native_file_dialog(dialog);
				return 0;
			}

			strncpy(filename, fn, 255);

			al_destroy_native_file_dialog(dialog);
			
			if(!load_level(filename))
				al_show_native_message_box(display, "Error", "Error", "The file you specified is either corrupt or not a valid level file. The file will not be opened.", NULL, ALLEGRO_MESSAGEBOX_ERROR);
			else
				saved = 1;
		}
	}
	else if(c==save_button && filename[0]!='\0')
	{
		if(!save_level(filename))
		{
			al_show_native_message_box(display, "Error", "Error", "The file could not be saved. Please ensure you have the appropriate permissions and that the path still exists.", NULL, ALLEGRO_MESSAGEBOX_ERROR);
			return 0;
		}

		saved = 1;
	}
	else if(c==saveas_button || c==save_button)
	{
			dialog = al_create_native_file_dialog("levels/", "Save Level", "*.*", ALLEGRO_FILECHOOSER_SAVE);
			
			if(!al_show_native_file_dialog(display, dialog))
				error_exit("Error: unable to display file chooser dialog!");

			if((fn=al_get_native_file_dialog_path(dialog, 0)) == NULL)
			{
				al_destroy_native_file_dialog(dialog);
				return 0;
			}

			if(!save_level(fn))
				al_show_native_message_box(display, "Error", "Error", "The file you specified is either corrupt or not a valid level file. The file will not be opened.", NULL, ALLEGRO_MESSAGEBOX_ERROR);
			else
			{
				strncpy(filename, fn, 255);
				saved = 1;
			}

			al_destroy_native_file_dialog(dialog);
	}

	return 0;
}

int select_grid_click(int mx, int my, struct _Clickable *c)
{
	int col = (mx - c->x1) / BRICK_W;
	int row = (my - c->y1) / BRICK_H;

	selected_index = col + (row*20);

	return 0;
}

void set_brick(int clear)
{
	if(clear)
	{
		bricks[brick_pos_i][brick_pos_j].img_index = -1;
		bricks[brick_pos_i][brick_pos_j].type = BRICK_TYPE_NONE;
	}
	else
	{
		bricks[brick_pos_i][brick_pos_j].img_index = selected_index;
		bricks[brick_pos_i][brick_pos_j].type = select_grid_types[selected_index];
	}

	saved = 0;
}

int brick_grid_click(int mx, int my, struct _Clickable *c)
{
	brick_pos_i = (c->x1-BRICK_GRID_X1) / BRICK_W;
	brick_pos_j = (c->y1-BRICK_GRID_Y1) / BRICK_H;

	if(left_mouse_button_down)
		set_brick(0);
	else if(right_mouse_button_down)
		set_brick(1);

	return 0;
}

int brick_grid_hover(int mx, int my, struct _Clickable *c, int on)
{
	if(on)
	{
		brick_pos_i = (c->x1-BRICK_GRID_X1) / BRICK_W;
		brick_pos_j = (c->y1-BRICK_GRID_Y1) / BRICK_H;

		if(left_mouse_button_down)
			set_brick(0);
		else if(right_mouse_button_down)
			set_brick(1);
	}

	return 0;
}

Clickable* make_button(ClickableSet *cs, int x, int y, char *text, int (*click)(int mx, int my, struct _Clickable *c))
{
	Clickable *c = NULL;

	c = malloc(sizeof(Clickable));
	c->parent_set = cs;
	c->icon = NULL;
	c->img = NULL;
	c->back_color = al_map_rgb(50,50,50);
	c->transparent = 0;
	c->font = editor_font;
	c->text_color = al_map_rgb(255,255,255);
	strncpy(c->text, text, 255);
	c->text_align = ALLEGRO_ALIGN_CENTRE;
	c->border_size = 2;
	c->border_color = al_map_rgb(200,200,200);
	c->x1 = x;
	c->y1 = y;
	c->x2 = c->x1 + 70;
	c->y2 = c->y1 + 20;
	c->hovering = 0;
	c->click = click;
	c->hover = NULL;
	reg_clickable(c);

	return c;
}

void draw_select_grid()
{
	int i = 0;

	for(i=0;i<40;i++)
	{
		if(i<20)
			al_draw_bitmap(brick_imgs[i], select_grid_clickable->x1+(BRICK_W*i), BRICK_GRID_Y2+15, 0);
		else
			al_draw_bitmap(brick_imgs[i], select_grid_clickable->x1+(BRICK_W*(i-20)), BRICK_GRID_Y2+15+BRICK_H, 0);
	}
}

int main(int argc, char **argv)
{
	int i = 0;
	int j = 0;

	APP_MODE = EDITOR;
	BRICK_GRID_X1 = 12;
	BRICK_GRID_Y1 = 62;
	BRICK_GRID_X2 = BRICK_GRID_X1 + (BRICK_GRID_W*BRICK_W);
	BRICK_GRID_Y2 = BRICK_GRID_Y1 + (BRICK_GRID_H*BRICK_H);

	if(!al_init())
		error_exit("failed to initialize allegro!");
 
	if(!al_init_image_addon())
		error_exit("failed to initialize image addon");

	al_init_font_addon();

	if(!al_init_ttf_addon())
		error_exit("failed to initialize ttf addon");

	if(!al_init_primitives_addon())
		error_exit("failed to initialize primitives addon");

	if(!al_install_mouse())
		error_exit("failed to initialize the mouse!");

	if(!al_install_keyboard())
		error_exit("failed to initialize the keyboard!");
 
	if(!(frame_timer = al_create_timer(1.0 / FPS)))
		error_exit("failed to create frame_timer!");

	if(!(display = al_create_display(SCREEN_W, SCREEN_H)))
		error_exit("failed to create display!");

	if(!(event_queue = al_create_event_queue()))
		error_exit("failed to create event_queue!");
 
	al_register_event_source(event_queue, al_get_display_event_source(display));
	al_register_event_source(event_queue, al_get_timer_event_source(frame_timer));
	al_register_event_source(event_queue, al_get_mouse_event_source());
	al_register_event_source(event_queue, al_get_keyboard_event_source());

	al_set_target_bitmap(al_get_backbuffer(display));
	al_clear_to_color(al_map_rgb(0,0,0));
	al_flip_display();

	for(i=0;i<40;i++)
	{
		select_grid_types[i] = BRICK_TYPE_NORMAL;
	}
	
	select_grid_types[37] = BRICK_TYPE_UNBREAKABLE;
	select_grid_types[38] = BRICK_TYPE_INVISIBLE;
	select_grid_types[39] = BRICK_TYPE_EXPLODING;

	load_images();
	load_level(NULL);

	editor_font = al_load_font("fonts/FreeMonoBold.ttf", 14, 0);

	main_set = new_clickable_set();

	for(j=0;j<BRICK_GRID_H;j++)
	{
		for(i=0;i<BRICK_GRID_W;i++)
		{
			brick_grid_clickables[i][j] = malloc(sizeof(Clickable));
			brick_grid_clickables[i][j]->parent_set = main_set;
			brick_grid_clickables[i][j]->icon = NULL;
			brick_grid_clickables[i][j]->img = NULL;
			brick_grid_clickables[i][j]->back_color = al_map_rgba(50,50,50,0);
			brick_grid_clickables[i][j]->transparent = 1;
			brick_grid_clickables[i][j]->font = editor_font;
			brick_grid_clickables[i][j]->text_color = al_map_rgb(255,255,255);
			brick_grid_clickables[i][j]->text[0] = '\0';
			brick_grid_clickables[i][j]->text_align = ALLEGRO_ALIGN_LEFT;
			brick_grid_clickables[i][j]->border_size = 0;
			brick_grid_clickables[i][j]->border_color = al_map_rgb(255,255,255);
			brick_grid_clickables[i][j]->x1 = bricks[i][j].x;
			brick_grid_clickables[i][j]->y1 = bricks[i][j].y;
			brick_grid_clickables[i][j]->x2 = bricks[i][j].x + BRICK_W;
			brick_grid_clickables[i][j]->y2 = bricks[i][j].y + BRICK_H;
			brick_grid_clickables[i][j]->hovering = 0;
			brick_grid_clickables[i][j]->click = &brick_grid_click;
			brick_grid_clickables[i][j]->hover = &brick_grid_hover;
			reg_clickable(brick_grid_clickables[i][j]);
		}
	}

	select_grid_clickable = malloc(sizeof(Clickable));
	select_grid_clickable->parent_set = main_set;
	select_grid_clickable->icon = NULL;
	select_grid_clickable->img = NULL;
	select_grid_clickable->back_color = al_map_rgb(50,50,50);
	select_grid_clickable->transparent = 1;
	select_grid_clickable->font = editor_font;
	select_grid_clickable->text_color = al_map_rgb(255,255,255);
	select_grid_clickable->text[0] = '\0';
	select_grid_clickable->text_align = ALLEGRO_ALIGN_CENTRE;
	select_grid_clickable->border_size = 2;
	select_grid_clickable->border_color = al_map_rgb(200,200,200);
	select_grid_clickable->x1 = BRICK_GRID_X1;
	select_grid_clickable->y1 = BRICK_GRID_Y2 + 15;
	select_grid_clickable->x2 = BRICK_GRID_X1 + SELECT_GRID_W*BRICK_W;
	select_grid_clickable->y2 = select_grid_clickable->y1 + (BRICK_H*SELECT_GRID_H);
	select_grid_clickable->hovering = 0;
	select_grid_clickable->click = &select_grid_click;
	select_grid_clickable->hover = NULL;
	reg_clickable(select_grid_clickable);

	new_button = make_button(main_set, BRICK_GRID_X1, 28, "New", &button_click);
	open_button = make_button(main_set, new_button->x2+8, new_button->y1, "Open", &button_click);
	save_button = make_button(main_set, open_button->x2+8, open_button->y1, "Save", &button_click);
	saveas_button = make_button(main_set, save_button->x2+8, save_button->y1, "Save As", &button_click);
	
	al_start_timer(frame_timer);

	while(1)
	{
		ALLEGRO_EVENT ev;
		al_wait_for_event(event_queue, &ev);
 
		if(ev.type == ALLEGRO_EVENT_TIMER)/* redraw screen */
		{
			al_clear_to_color(al_map_rgb(0,0,0));
			
			/* draw the bricks and the brick border/frame */
			draw_bricks(1);
			draw_outside_border(BRICK_GRID_X1, BRICK_GRID_Y1, BRICK_GRID_X2, BRICK_GRID_Y2, al_map_rgb(255,255,255), 2);

			draw_select_grid();
			draw_clickable(select_grid_clickable);

			draw_clickable(new_button);
			draw_clickable(open_button);
			draw_clickable(save_button);
			draw_clickable(saveas_button);

			al_draw_text(editor_font, al_map_rgb(255,255,0), BRICK_GRID_X1, 4, 0, "FILENAME: ");
			al_draw_text(editor_font, al_map_rgb(255,255,255), BRICK_GRID_X1+80, 4, 0, filename);

			al_draw_text(editor_font, al_map_rgb(255,255,0), 540, 32, 0, "POS: ");

			if(mouse_pos_x>=BRICK_GRID_X1 && mouse_pos_x<=BRICK_GRID_X2 && mouse_pos_y>=BRICK_GRID_Y1 && mouse_pos_y<=BRICK_GRID_Y2)
				al_draw_textf(editor_font, al_map_rgb(255,255,255), 580, 32, 0, "%d, %d", brick_pos_i, brick_pos_j);

			al_draw_text(editor_font, al_map_rgb(255,255,0), 652, 32, 0, "SELECTED:");
			al_draw_bitmap(brick_imgs[selected_index], 736, 30, 0);

			al_flip_display();
		}
		else if(ev.type == ALLEGRO_EVENT_KEY_UP)
		{}
		else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES)
		{
			mouse_pos_x = ev.mouse.x;
			mouse_pos_y = ev.mouse.y;
			process_clickable_set_hovers(main_set, ev.mouse.x, ev.mouse.y);
		}
		else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
		{
			if(ev.mouse.button == 1)
				left_mouse_button_down = 1;
			else if(ev.mouse.button == 2)
				right_mouse_button_down = 1;

			process_clickable_set_clicks(main_set, ev.mouse.x, ev.mouse.y);
		}
		else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)
		{
			if(ev.mouse.button == 1)
				left_mouse_button_down = 0;
			else if(ev.mouse.button == 2)
				right_mouse_button_down = 0;
		}
		else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
		{
			if(saved || al_show_native_message_box(display, "Warning!", "Warning!", "You have unsaved changes. Are you sure you want to continue?", NULL, ALLEGRO_MESSAGEBOX_YES_NO) == 1)
				break;
		}
	}
 
	clean_up();
	return 0;
}






